#ifndef _HTTP_LOG_PARSER_H
#define _HTTP_LOG_PARSER_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dataset.h>
#include <time.h>

typedef union un_ip {
	unsigned int dword;
	struct st_ip_parts {
		unsigned char d;
		unsigned char c;
		unsigned char b;
		unsigned char a;
	} parts;
} IP;

typedef struct st_time {
	unsigned short year;
	unsigned char month;
	unsigned char date;
	unsigned char hour;
	unsigned char minute;
	unsigned char second;
#define TZ_FLAG_WEST 0
#define TZ_FLAG_EAST 1
	unsigned char tz_flag;
	unsigned char tz_hour;
	unsigned char tz_minute;
} Time;

// utils

static struct tm to_tm(Time date) {
	struct tm t = {0};
	t.tm_year = date.year - 1900;
	t.tm_mon = date.month;
	t.tm_mday = date.date;
	t.tm_hour = date.hour;
	t.tm_min = date.minute;
	t.tm_sec = date.second;
	return t;
}

static time_t to_time_t(Time date) {
	struct tm t = to_tm(date);
	return mktime(&t);
}

static Time to_date(time_t t) {
	struct tm * p = localtime(&t);
	Time date;
	date.year = p->tm_year + 1900;
	date.month = p->tm_mon;
	date.date = p->tm_mday;
	date.hour = p->tm_hour;
	date.minute = p->tm_min;
	date.second = p->tm_sec;
	return date;
}

static Time get_current_date() {
	time_t now;
	time(&now);
	return to_date(now);
}

static long long diff_seconds(Time d1, Time d2) {
	struct tm t1 = to_tm(d1), t2 = to_tm(d2);
	return (long long) difftime(mktime(&t1), mktime(&t2));
}

//-------------------------------------


#define MAX_PATH_LEN 128
#define MAX_PARAM_KEY_LEN 64
#define MAX_PARAM_VALUE_LEN 512
#define MAX_ANCHOR_LEN 64
#define MAX_URI_LEN 1024
#define MAX_TMP_BUFFER_LEN MAX_URI_LEN

#define MAX(x, y) (x > y ? x : y)

typedef struct st_uri {
	char path[MAX_PATH_LEN];
	map * params;
	char anchor[MAX_ANCHOR_LEN];
} URI;

void discard_uri(URI * pURI);

int parse_uri(URI * pURI, const char * uri, unsigned int pos);

inline char * str_param(map *params, const char *key,
		const char *def_value);

inline int int_param(map *params, const char *key, int def_value);

inline float float_param(map *params, const char *key, float def_value);

inline double double_param(map *params, const char *key,
		double def_value);
//-------------------------------------------------------------------------

#define IP_LEN           16
#define IDENTITY_LEN     16
#define USERID_LEN       16
#define METHOD_LEN       8
#define URL_LEN          MAX_URI_LEN
#define PROTOCOL_LEN     16
#define REFERER_LEN      URL_LEN
#define USER_AGENT_LEN   512

#define MAX_LOG_ENTRY_LEN (IP_LEN+IDENTITY_LEN+USERID_LEN+METHOD_LEN+URL_LEN+PROTOCOL_LEN+REFERER_LEN+USER_AGENT_LEN+472)

#define MAX_INT_LEN      16

/**
 * Http Log Entry
 */
typedef struct st_http_log_entry {
	IP ip;
	char identity[IDENTITY_LEN];
	char userid[USERID_LEN];
	Time time;
	char method[METHOD_LEN];
	char url[URL_LEN];
	URI uri;
	char protocol[PROTOCOL_LEN];
	unsigned short status;
	unsigned int bytes;
	char referer[REFERER_LEN];
	char user_agent[USER_AGENT_LEN];
} HttpLogEntry;

#define Jan ("Jan")
#define Feb ("Feb")
#define Mar ("Mar")
#define Apr ("Apr")
#define May ("May")
#define Jun ("Jun")
#define Jul ("Jul")
#define Aug ("Aug")
#define Sep ("Sep")
#define Oct ("Oct")
#define Nov ("Nov")
#define Dec ("Dec")

#define GET_MONTH(x) (\
strcmp(x, Jan) == 0 ? 0 :\
strcmp(x, Feb) == 0 ? 1 :\
strcmp(x, Mar) == 0 ? 2 :\
strcmp(x, Apr) == 0 ? 3 :\
strcmp(x, May) == 0 ? 4 :\
strcmp(x, Jun) == 0 ? 5 :\
strcmp(x, Jul) == 0 ? 6 :\
strcmp(x, Aug) == 0 ? 7 :\
strcmp(x, Sep) == 0 ? 8 :\
strcmp(x, Oct) == 0 ? 9 :\
strcmp(x, Nov) == 0 ? 10 :\
strcmp(x, Dec) == 0 ? 11 : -1)

void discard_http_log_entry(HttpLogEntry * pEntry);

int parse_http_log_entry(HttpLogEntry * pEntry, const char* line);

#endif /* _HTTP_H */
